package com.mystudyspring.studySpringBoot.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.mystudyspring.studySpringBoot.domain.LoggerEntity;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;

/**
 * api请求日志,拦截器
 *
 * @author lix
 * @create 2018-03-22 18:01
 */
public class ApiLogInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        LoggerEntity loggerEntity = new LoggerEntity();
        String sessionId = request.getRequestedSessionId();
        String url = request.getRequestURI();
        String contentType = request.getContentType();
        System.out.println("getContentType:" + contentType);
        //todo:记录客户端的信息
        loggerEntity.setSessionId(sessionId);
        loggerEntity.setUrl(url);

        loggerEntity.setContentType(contentType);
        String paramsData = "";
        //todo:如果是访问的静态资源，则不需要记录太多数据
        if (url.indexOf("resources") > 0) {
            //todo:开始时间
            request.setAttribute("LOGGER_SEND_TIME", System.currentTimeMillis());
            request.setAttribute("LOGGER_ENTITY", loggerEntity);

            System.out.println("api preHandle 请求日志信息:" + JSON.toJSONString(loggerEntity));

            return true;
        }

        if (contentType != null && !contentType.isEmpty()) {
            if (contentType.equals("application/json")) {
                //todo:如果是application/json 请求，则获取的参数方式不一样
                if (request.getMethod().equals("GET")) {
                    paramsData = request.getQueryString() == null ? ""
                            : new String(request.getQueryString().getBytes("iso-8859-1"), "utf-8").replaceAll("%22", "\"");
                } else {
                    paramsData = getRequestPostStr(request);
                }
            } else {
                //todo:application/x-www-form-urlencoded
                if (request.getMethod().equals("GET")) {
                    paramsData = request.getQueryString() == null ? ""
                            : new String(request.getQueryString().getBytes("iso-8859-1"), "utf-8").replaceAll("%22", "\"");
                } else {
                    paramsData = getParamString(request.getParameterMap());
                }
            }
        }

        loggerEntity.setParamData(paramsData);
        //todo:开始时间
        request.setAttribute("LOGGER_SEND_TIME", System.currentTimeMillis());
        request.setAttribute("LOGGER_ENTITY", loggerEntity);

        System.out.println("api preHandle 请求日志信息:" + JSON.toJSONString(loggerEntity));

        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

        //todo:获取preHandle的属性信息
        //todo:写入到文件或者数据库，AOP原理都一样
        int status = response.getStatus();
        long endTime = System.currentTimeMillis();
        long startTime = Long.valueOf(request.getAttribute("LOGGER_SEND_TIME").toString());
        LoggerEntity loggerEntity = (LoggerEntity) request.getAttribute("LOGGER_ENTITY");

        loggerEntity.setReturnTime(endTime + "");
        loggerEntity.setHttpStatus(status);
        loggerEntity.setReturnData(JSON.toJSONString(request.getAttribute(LoggerUtils.LOGGER_RETURN),
                SerializerFeature.DisableCircularReferenceDetect,
                SerializerFeature.WriteMapNullValue));

        String result = JSON.toJSONString(loggerEntity);

        System.out.println("api afterCompletion 请求日志信息:" + result);
    }

    /**
     * 描述:获取 post 请求的 byte[] 数组
     * <pre>
     * 举例：
     * </pre>
     *
     * @param request
     * @return
     * @throws IOException
     */
    public byte[] getRequestPostBytes(HttpServletRequest request)
            throws IOException {
        int contentLength = request.getContentLength();
        if (contentLength < 0) {
            return null;
        }
        byte buffer[] = new byte[contentLength];
        for (int i = 0; i < contentLength; ) {

            int readlen = request.getInputStream().read(buffer, i,
                    contentLength - i);
            if (readlen == -1) {
                break;
            }
            i += readlen;
        }
        return buffer;
    }

    /**
     * 描述:获取 post 请求内容
     * <pre>
     * 举例：
     * </pre>
     *
     * @param request
     * @return
     * @throws IOException
     */
    public String getRequestPostStr(HttpServletRequest request)
            throws IOException {
        byte buffer[] = getRequestPostBytes(request);
        String charEncoding = request.getCharacterEncoding();
        if (charEncoding == null) {
            charEncoding = "UTF-8";
        }
        return new String(buffer, charEncoding);
    }

    private String getParamString(Map<String, String[]> map) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String[]> e : map.entrySet()) {
            sb.append(e.getKey()).append("=");
            String[] value = e.getValue();
            if (value != null && value.length == 1) {
                sb.append(value[0]).append("&");
            } else {
                sb.append(Arrays.toString(value)).append("&");
            }
        }
        return sb.toString();
    }

    /**
     * 判断是否为ajax请求
     *
     * @param request
     * @return
     */
    public static String getRequestType(HttpServletRequest request) {
        return request.getHeader("X-Requested-With");
    }
}
